package com.inepex.inechart.client.axes;

import java.util.List;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.inepex.inechart.shared.CartesianException;
import com.inepex.inechart.shared.axes.Axis;
import com.inepex.inechart.shared.axes.AxisDirection;
import com.inepex.inegraphics.impl.client.IncrementalProgress.IncrementalProgressCaller;

public abstract class IncrementalAxisCalculator implements IncrementalProgressCaller{

	protected int updatePartTresHold;
	protected AxisCalculatorGWT target;
	protected List<Axis> axes;
	protected AxesGWT axesGwt;
	protected int actualAxisIndex;
	protected boolean paddingCalculation;
	protected double xFrom, xTo, yFrom, yTo;

	public IncrementalAxisCalculator(int updatePartTresHold, List<Axis> axes,
			AxesGWT axesGwt, boolean paddingCalculation, double xFrom,
			double xTo, double yFrom, double yTo) throws CartesianException {
		super();
		this.updatePartTresHold = updatePartTresHold;
		this.axes = axes;
		this.axesGwt = axesGwt;
		this.paddingCalculation = paddingCalculation;
		this.xFrom = xFrom;
		this.xTo = xTo;
		this.yFrom = yFrom;
		this.yTo = yTo;
		actualAxisIndex = -1;
		nextTargetOrFinish();
	}

	protected void nextTargetOrFinish() throws CartesianException{
		if(++actualAxisIndex >= axes.size()){
			onFinish();
		}
		else{
			Axis actAxis = axes.get(actualAxisIndex);
			target = axesGwt.axisToAxisCalcMap.get(actAxis);
			double from, to;
			if(AxisDirection.isPerpendicular(actAxis.getModulToAlign().getXAxis(), actAxis)){ //y
				from = yFrom;
				to = yTo;
			}
			else{
				from = xFrom;
				to = xTo;
			}
			if(paddingCalculation){
				target.initForPaddingCalc(from, to);
			}
			else{
				target.initForGOCreation(from, to);
			}
			target.initProgress(this);
			Scheduler.get().scheduleIncremental(new RepeatingCommand() {

				@Override
				public boolean execute() {
					boolean inProgress = IncrementalAxisCalculator.this.target.nextProgressPart();
					if(!inProgress){
						try {
							nextTargetOrFinish();
						} catch (CartesianException e) {
							e.printStackTrace();
							return false;
						}				
					}
					return inProgress;				
				}
			});
		}
	}

	@Override
	public int getProgressPartTresholdMS() {
		return updatePartTresHold;
	}

	protected abstract void onFinish();

}
